﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Workflow
//  File name:	WorkflowService.cs
//  Developer:	Solomatov Igor
//  Created:	16.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;
using Smart.Common;

namespace Smart.Workflow
{
	/// <summary>
	/// Workflow customization service
	/// </summary>
	public class WorkflowService : IWorkflowService
	{
		/// <summary>
		/// Returns service by name
		/// </summary>
		public static IWorkflowService GetService(SPWorkflowActivationProperties workflowProperties, ActivityProperties activityProperties)
		{
			var service = SPServices.ServiceLocator.GetInstance<IWorkflowService>(activityProperties.WorkflowServiceName);

			if (service == null)
				throw new InvalidOperationException(string.Format("WorkflowService '{0}' is not registered!", activityProperties.WorkflowServiceName));

			service.Init(workflowProperties, activityProperties);

			return service;
		}

		/// <summary>
		/// Workflow properties
		/// </summary>
		public SPWorkflowActivationProperties WorkflowProperties { get; set; }

		/// <summary>
		/// Activity properties
		/// </summary>
		public ActivityProperties ActivityProperties { get; set; }

		/// <summary>
		/// Additional notification fields
		/// </summary>
		public Dictionary<string, object> NotificationFields { get; set; }

		/// <summary>
		/// Initialize service
		/// </summary>
		public virtual void Init(SPWorkflowActivationProperties workflowProperties, ActivityProperties activityProperties)
		{
			WorkflowProperties = workflowProperties;
			ActivityProperties = activityProperties;
			NotificationFields = null;
		}

		/// <summary>
		/// Returns task ContentTypeId by <paramref name="taskType"/>
		/// </summary>
		public virtual string GetTaskContentTypeId(TaskType taskType)
		{
			switch (taskType)
			{
				case TaskType.None:
					return null;

				case TaskType.Read:
					return "0x01080100B53F82F467B14F2E9DFD2DA17C2D211C02";

				case TaskType.Approve:
					return "0x01080100B53F82F467B14F2E9DFD2DA17C2D211C01";

				case TaskType.Sign:
					throw new NotImplementedException();

				case TaskType.Execute:
					throw new NotImplementedException();

				default:
					throw new ArgumentOutOfRangeException("taskType");
			}
		}

		/// <summary>
		/// Returns message template
		/// </summary>
		public virtual string GetHistoryMessageTemplate(string eventType)
		{
			if (eventType.IsNullOrEmpty() || eventType.EqIC(WorkflowEventTypes.None))
				return null;

			var template = ("History_" + eventType).Localized();

			if (template.StartsWith("$Resources"))
				throw new ArgumentOutOfRangeException("eventType");

			return template;
		}

		/// <summary>
		/// Returns notification template name
		/// </summary>
		public virtual string GetNotificationTemplateName(string eventType)
		{
			if (eventType.IsNullOrEmpty() || eventType.EqIC(WorkflowEventTypes.None))
				return null;

			return ("Workflow_Notification_" + eventType).Localized();
		}

		/// <summary>
		/// Sends notification message to Assignee email
		/// </summary>
		public virtual void SendNotification(string eventType, SPListItem taskItem, SPWorkflowTaskProperties properties, Dictionary<string, object> values)
		{
			SendNotification(eventType, null, taskItem, properties, values);
		}

		/// <summary>
		/// Sends notification message to <paramref name="emails"/>
		/// </summary>
		public virtual void SendNotification(string eventType, string emails, SPListItem taskItem, SPWorkflowTaskProperties properties, Dictionary<string, object> values)
		{
			if (values == null)
				values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

			//var web = SPH.GetWeb();

			properties.GetTaskValues(WorkflowProperties.Web, WorkflowProperties.Item, taskItem, NotificationFields, values);

			var templateName = GetNotificationTemplateName(eventType);

			using (var notifications = SPServices.Notifications)
			using (new UnsafeUpdate(notifications.Web))
			{
				if (emails.IsNullOrEmpty())
					emails = WorkflowProperties.Web.GetPrincipal(properties.AssignedTo).GetEmails();

				var queued =
					notifications.QueueItem(templateName, emails, values);

				if (!queued)
					H.LT("WorkflowService.SendNotification.Exception: QueueItem failed for '{0}'!", emails);
			}
		}

		/// <summary>
		/// Returns values for rules service
		/// </summary>
		public virtual void FillRulesValues(Dictionary<string, object> values)
		{
			values["WorkflowName"] = WorkflowProperties.TemplateName;
			values["WorkflowOriginator"] = WorkflowProperties.Originator;
			values["WorkflowOriginatorEmail"] = WorkflowProperties.OriginatorEmail;
		}

		/// <summary>
		/// Perform action from rules on Workflow
		/// </summary>
		public virtual bool PerformAction(string actionName, string[] actionArgs, out bool handled)
		{
			handled = false;
			return false;
		}

		/// <summary>
		/// Execute Workflow rule condition function
		/// </summary>
		public virtual bool ExecuteFunction(string functionName, string[] functionArgs, out bool handled)
		{
			handled = false;
			return false;
		}
	}
}